#pragma once
#include <glm/glm.hpp>
#include "Config.h"
#include "Uniform.h"

namespace Light {

enum Type { Directional, Point, Spot };

static const CColor GlobalAmbient = "white";

class Directional {
public:
	static Directional* get() {
		static auto* instance = new Directional;
		return instance;
	}

	void setWorldDirection(const Vec3& worldDirection) { m_worldDirection = worldDirection; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }

	void setAsUniform(Uniform& uniform) {
		uniform.add("directional.worldDirection", m_worldDirection);
		uniform.add("directional.intensity", m_intensity);
		uniform.add("directional.color", m_color);
	}

private:
	Directional() = default;

	Vec3 m_worldDirection = Config::Light_Directional_WorldDirection;
	CColor m_color = Config::Light_Directional_Color;
	float m_intensity = Config::Light_Directional_Intensity;
};

class Point {
public:
	static Point* get() {
		static auto* instance = new Point;
		return instance;
	}

	void setPosition(const Vec3& position) { m_position = position; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }
	void setConstAtt(float consAtt) { m_constAtt = consAtt; }
	void setLinearAtt(float linearAtt) { m_linearAtt = linearAtt; }
	void setQuadAtt(float quadAtt) { m_quadAtt = quadAtt; }

	void setAsUniform(Uniform& uniform) {
		uniform.add("point.position", m_position);
		uniform.add("point.intensity", m_intensity);
		uniform.add("point.constAtt", m_constAtt);
		uniform.add("point.linearAtt", m_linearAtt);
		uniform.add("point.quadAtt", m_quadAtt);
		uniform.add("point.color", m_color);
	}

private:
	Point() = default;

	Vec3 m_position = Config::Light_Point_Position;
	CColor m_color = Config::Light_Point_Color;
	float m_intensity = Config::Light_Point_Intensity;
	float m_constAtt = Config::Light_Point_ConstAtt;
	float m_linearAtt = Config::Light_Point_LinearAtt;
	float m_quadAtt = Config::Light_Point_QuadAtt;
};

class Spot {
public:
	static Spot* get() {
		static auto* instance = new Spot;
		return instance;
	}

	void setPosition(const Vec3& position) { m_position = position; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }
	void setLocalDirection(const Vec3& localDirection) { m_localDirection = localDirection; }
	void setCutOffAngle(float cutOffAngle) { m_cutOffAngle = cutOffAngle; }
	void setConstAtt(float constAtt) { m_constAtt = constAtt; }
	void setLinearAtt(float linearAtt) { m_linearAtt = linearAtt; }
	void setQuadAtt(float quadAtt) { m_quadAtt = quadAtt; }

	void setAsUniform(Uniform& uniform) {
		uniform.add("point.position", m_position);
		uniform.add("point.intensity", m_intensity);
		uniform.add("point.localDirection", m_localDirection);
		uniform.add("point.cutOffAngle", m_cutOffAngle);
		uniform.add("point.constAtt", m_constAtt);
		uniform.add("point.linearAtt", m_linearAtt);
		uniform.add("point.quadAtt", m_quadAtt);
		uniform.add("point.color", m_color);
	}

private:
	Spot() = default;

	Vec3 m_position;
	CColor m_color;
	float m_intensity;
	Vec3 m_localDirection;
	float m_cutOffAngle;
	float m_constAtt;
	float m_linearAtt;
	float m_quadAtt;
};

}// end namespace